/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.controller;

/**
 *
 * @author Laurent WOUTERS
 */
public class DataPlaceholder extends ASTElement {
    private interface Manager extends xowl.gmi.view.diagram.DataPlaceholder.Actions {
        void onValueChanged(Object value);
        void decommission();
    }
    
    private Manager manager;
    private xowl.gmi.model.cvssl.DataPlaceholder definition;
    private xowl.gmi.view.diagram.DataPlaceholder widget;
    
    public DataPlaceholder(Controller controller, Element parent, xowl.gmi.model.cvssl.DataPlaceholder def, xowl.gmi.model.ast.ASTNode ast) {
        super(controller, parent, ast);
        this.definition = def;
        buildManager(definition);
        Integer width = getValueInteger(definition.getWidth(), getObserverWidth());
        if (width == null) width = 10;
        Integer height = getValueInteger(definition.getHeight(), getObserverHeight());
        if (height == null) height = 10;
        Boolean isFill = definition.getIsFill();
        if (isFill == null) isFill = false;
        java.awt.Font font = null;
        java.awt.Color fontColor = null;
        if (definition.getFont() != null) {
            String name = getValueString(definition.getFont().getFontName(), getObserverFontName());
            if (name == null) name = "Arial";
            int style = getFontStyle(definition.getFont());
            Integer size = getValueInteger(definition.getFont().getFontSize(), getObserverFontSize());
            if (size == null) size = 10;
            fontColor = getValueColor(definition.getFont().getFontColor(), getObserverFontColor());
            font = new java.awt.Font(name, style, size);
        }
        widget = new xowl.gmi.view.diagram.DataPlaceholder(manager, controller.getLocale(), width, height, isFill, font, fontColor, manager.getValue());
    }
    
    private xowl.interpreter.adapter.DataPropertyObserver getObserverWidth() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                widget.setWidth((Integer)elem);
                controller.onDiagramUpdated();
            }
            @Override public void onRemove(Object elem) { }
        };
    }
    private xowl.interpreter.adapter.DataPropertyObserver getObserverHeight() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                widget.setHeight((Integer)elem);
                controller.onDiagramUpdated();
            }
            @Override public void onRemove(Object elem) { }
        };
    }
    private xowl.interpreter.adapter.DataPropertyObserver getObserverFontName() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                widget.setFontName((String)elem);
                controller.onDiagramUpdated();
            }
            @Override public void onRemove(Object elem) { }
        };
    }
    private xowl.interpreter.adapter.DataPropertyObserver getObserverFontSize() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                widget.setFontSize((Integer)elem);
                controller.onDiagramUpdated();
            }
            @Override public void onRemove(Object elem) { }
        };
    }
    private xowl.interpreter.adapter.DataPropertyObserver getObserverFontColor() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                widget.setFontColor(new java.awt.Color((Integer)elem));
                controller.onDiagramUpdated();
            }
            @Override public void onRemove(Object elem) { }
        };
    }
    
    @Override public xowl.gmi.view.diagram.Widget getWidget() { return widget; }
    
    @Override protected void onChildAdd(xowl.gmi.model.ast.ASTNode node) {}
    @Override protected void onChildRemove(xowl.gmi.model.ast.ASTNode node) {}
    
    @Override public void saveTo(xowl.gmi.model.Diagram diagram) { }
    @Override public void decommission() {
        manager.decommission();
        decommissionListeners();
    }
    
    private void setTokenValue(Object previous, Object newValue) {
        DiagramUIAction action = new DiagramUIAction(controller.getLocale().diagSetValue + " " + newValue.toString());
        if (previous != null)
            action.addInner(controller.getCommandBuilder().unset(astNode.getEntity().getHasIRI(), previous));
        action.addInner(controller.getCommandBuilder().set(astNode.getEntity().getHasIRI(), newValue));
        controller.executeUIAction(action);
    }
    
    private xowl.interpreter.adapter.DataPropertyObserver getObserver() {
        return new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) { manager.onValueChanged(elem); }
            @Override public void onRemove(Object elem) { manager.onValueChanged(null); }
        };
    }
    
    private void buildManager(xowl.gmi.model.cvssl.DataPlaceholder definition) {
        if (definition instanceof xowl.gmi.model.cvssl.StringDataPlaceholder) {
            this.manager = new Manager() {
                private xowl.gmi.model.ast.StringToken token;
                private String current;
                {
                    token = (xowl.gmi.model.ast.StringToken)astNode.getSymbol();
                    current = token.getDataString();
                    token.addPropertyObserver("dataString", getObserver());
                }
                @Override public boolean isValid(String data) { return true; }
                @Override public String getValue() { return current; }
                @Override public void setValue(String data) { setTokenValue(current, data); }
                @Override public void onValueChanged(Object value) {
                    current = (String)value;
                    widget.setValue(current);
                    controller.onDiagramUpdated();
                }
                @Override public void decommission() { token.removeAllObservers(); }
            };
        } else if (definition instanceof xowl.gmi.model.cvssl.IntegerDataPlaceholder) {
            this.manager = new Manager() {
                private xowl.gmi.model.ast.IntegerToken token;
                private Integer current;
                {
                    token = (xowl.gmi.model.ast.IntegerToken)astNode.getSymbol();
                    current = token.getDataInteger();
                    token.addPropertyObserver("dataInteger", getObserver());
                }
                @Override public boolean isValid(String data) {
                    try {
                        Integer value = Integer.parseInt(data);
                        return true;
                    } catch (java.lang.NumberFormatException ex) {
                        return false;
                    }
                }
                @Override public String getValue() {
                    if (current == null)
                        return null;
                    return current.toString();
                }
                @Override public void setValue(String data) { setTokenValue(current, data); }
                @Override public void onValueChanged(Object value) {
                    current = (Integer)value;
                    widget.setValue((current == null) ? null : current.toString());
                    controller.onDiagramUpdated();
                }
                @Override public void decommission() { token.removeAllObservers(); }
            };
        } else if (definition instanceof xowl.gmi.model.cvssl.FloatDataPlaceholder) {
            this.manager = new Manager() {
                private xowl.gmi.model.ast.FloatToken token;
                private Float current;
                {
                    token = (xowl.gmi.model.ast.FloatToken)astNode.getSymbol();
                    current = token.getDataFloat();
                    token.addPropertyObserver("dataFloat", getObserver());
                }
                @Override public boolean isValid(String data) {
                    try {
                        Float value = Float.parseFloat(data);
                        return true;
                    } catch (java.lang.NumberFormatException ex) {
                        return false;
                    }
                }
                @Override public String getValue() {
                    if (current == null)
                        return null;
                    return current.toString();
                }
                @Override public void setValue(String data) { setTokenValue(current, data); }
                @Override public void onValueChanged(Object value) {
                    current = (Float)value;
                    widget.setValue((current == null) ? null : current.toString());
                    controller.onDiagramUpdated();
                }
                @Override public void decommission() { token.removeAllObservers(); }
            };
        }
    }
}
